package net.javamine.base;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import net.javamine.util.CollectionUtils;
import net.javamine.util.ExceptionUtils;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 * HibernateForMySQLDAO基类
 * 
 * @author <a href="mailto: java_lht@163.com">Lht</a>
 * @since 2012-10-04
 * @version 1.0
 */
@Repository("baseDao")
public class BaseHibernateForMySQLDao {
	
	@Autowired
	private SessionFactory sessionFactory;
	
	private static Logger log = Logger.getLogger(BaseHibernateForMySQLDao.class);

	/**
	 * 获取hibernateSession对象
	 * @return hibernateSession对象
	 */
	private Session getSession() {
		return sessionFactory.getCurrentSession();
	}
	
	/**
	 * 保存对象
	 * @param entity 需要保存的对象
	 */
	public <T> void save(T entity) {
		try {
			this.getSession().save(entity);
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
		}
	}

	/**
	 * 删除对象
	 * @param entity 需要删除的对象（设置好对象的ID即可）
	 */
	public <T> void delete(T entity) {
		try {
			this.getSession().delete(entity);
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
		}
	}
	
	/**
	 * 根据ID删除对象
	 * @param clazz 类.Class 
	 * @param id 对象的ID
	 */
	@SuppressWarnings("unchecked")
	public <T> void deleteById(Class<T> clazz, long id) {
		try {
			this.getSession().delete((T) this.getSession().get(clazz, id));
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
		}
	}

	/**
	 * 更新对象
	 * @param entity 需要更新的对象（需要ID）
	 */
	public <T> void update(T entity) {
		try {
			this.getSession().update(entity);
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
		}
	}
	
	/**
	 * 保存或更新 对象
	 * @param entity 需要保存或更新的对象（需要ID）
	 */
	public <T> void saveOrUpdate(T entity) {
		try {
			this.getSession().saveOrUpdate(entity);
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
		}
	}
	
	/**
	 * 使用HQL执行操作（增删改）
	 * @param hql 需要执行的HQL语句
	 * @param paramsMap <:name, value> HQL语句中需要使用：name的方式
	 */
	public int executeByHQL(String hql, Map<String, Object> paramsMap) {
		try {
			return this.getQueryByHQLAndParamsMap(hql, paramsMap).executeUpdate();
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
			return 0;
		}
	}
	
	/**
	 * 使用HQL执行查询对象
	 * @param hql 需要执行的HQL语句
	 * @param T 类.Class
	 * @param paramsMap <:name, value> HQL语句中需要使用：name的方式
	 */
	@SuppressWarnings("unchecked")
	public <T> T queryObjectByHQL(String hql, Class<T> T, Map<String, Object> paramsMap) {
		try {
			List<T> list = this.getQueryByHQLAndParamsMap(hql, paramsMap).list();
			if (CollectionUtils.listIsNotEmpty(list)) {
				return (T) list.get(0);
			} else {
				return null;
			}
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
		}
		return null;
	}
	
	/**
	 * 根据HQL查询List
	 * @param hql 需要执行的HQL语句
	 * @param T 类.Class
	 * @param paramsMap <:name, value> HQL语句中需要使用：name的方式
	 * @return 包含指定对象的List
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> queryListByHQL(String hql, Class<T> T, Map<String, Object> paramsMap) {
		try {
			return (List<T>) this.getQueryByHQLAndParamsMap(hql, paramsMap).list();
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
		}
		return null;
	}
	
	/**
	 * 根据HQL语句和对象相关属性和值组装的Query对象
	 * @param hql 需要执行的HQL语句
	 * @param paramsMap	<:name, value> HQL语句中需要使用：name的方式
	 * @return 组装好的Query对象
	 */
	private Query getQueryByHQLAndParamsMap(String hql, Map<String, Object> paramsMap) {
		Query query = getSession().createQuery(hql);
		for (String paramName : paramsMap.keySet()) {
			Object value = paramsMap.get(paramName);
			if (value instanceof Collection) {
				query.setParameterList(paramName, (Collection<?>) value);
			} else if (value.getClass().isArray()) {
				query.setParameterList(paramName, (Object[]) value);
			} else {
				query.setParameter(paramName, value);
			}
		}
		return query;
	}
	
	/**
	 * 根据ID查找对象
	 * @param T 类.Class
	 * @param id 对象的ID
	 * @return 需要查询的指定对象
	 */
	@SuppressWarnings("unchecked")
	public <T> T queryObjectById(Class<T> T, long id) {
		try {
			return (T) this.getSession().get(T, id);
		} catch (Exception e) {
			ExceptionUtils.getExceptionMessage(log, e);
		}
		return null;
	}
	
}
